package com.example.base_model.network.interceptor

import android.Manifest
import androidx.annotation.RequiresPermission
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.DeviceUtils
import com.blankj.utilcode.util.NetworkUtils
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import jakarta.inject.Inject
import okhttp3.Interceptor
import okhttp3.Response
import okhttp3.ResponseBody
import java.io.IOException

/**
 * @Author: jiangKunKun
 * @CreateDate: 2025/7/14
 * @Description: 一个OkHttp拦截器，主要作用是为每个发出的网络请求统一添加公共的请求头。
 * @SpittingGrooves
 */
class StatusInterceptor @Inject constructor(
    private val moshi: Moshi
): Interceptor {
    val jsonAdapter = moshi.adapter<Map<String, Any?>>(Map::class.java)
        .nullSafe() as JsonAdapter<Map<String, Any?>>
    /**
     * 实现Interceptor接口的核心方法，在此处拦截并修改请求。
     * @param chain 拦截器链，通过它我们可以获取原始请求并继续执行请求。
     * @return Response 修改或处理后的响应。
     */
    @RequiresPermission(Manifest.permission.INTERNET) // 标注此方法需要网络权限
    @Throws(IOException::class) // 声明此方法可能抛出IO异常
    override fun intercept(chain: Interceptor.Chain): Response {
        // 首先检查网络是否可用，如果网络不可用，则直接继续原始请求，让OkHttp自行处理网络错误。
        if (!NetworkUtils.isAvailable()) {
            return chain.proceed(chain.request())
        }

        // 获取原始的请求对象
        val originalRequest = chain.request()

        // 使用newBuilder()创建一个新的请求构建器，在原始请求的基础上进行修改
        val request = originalRequest.newBuilder()
            // 添加设备型号作为请求头
            .addHeader("device-version", DeviceUtils.getModel())
            // 添加设备操作系统类型为 "Android"
            .addHeader("device-os", "Android")
            // 添加设备的唯一标识ID
            .addHeader("device-id", DeviceUtils.getUniqueDeviceId())
            // 添加安卓系统的SDK版本名称 (例如 "11", "12")
            .addHeader("device-os-version", DeviceUtils.getSDKVersionName())
            // 添加请求来源标识，"3"可能代表特定客户端类型
            .addHeader("source", "3")
            // 添加当前App的版本名称 (例如 "1.0.0")
            .addHeader("app-version", AppUtils.getAppVersionName())
            // 添加端口标识，"app"表示来自App端
            .addHeader("port", "app")
            // 添加token请求头，这里默认为空字符串，实际项目中通常会从本地存储中动态获取
            .addHeader("token", "")
            // 构建一个新的、包含了所有新请求头的请求对象
            .build()

        // 使用构建好的新请求，继续执行网络请求链，并获取响应
        // 这一步是实际发出网络请求的地方，并且在整个拦截器中只应调用一次 chain.proceed()
        val response = chain.proceed(request)

        // --- 响应体处理 ---
        // 为了可以安全地读取响应体内容（例如用于日志记录或统一的业务逻辑判断），同时又不影响后续调用者对响应体的读取，
        // 我们需要先克隆响应体。因为 ResponseBody 的内容流只能被读取一次。

        val responseBody = response.body
        val responseString = responseBody?.string() // 将响应体内容读取为字符串，此操作会消耗掉原始的响应体流

        var businessCode: Int? = null
        try {
            val jsonAdapter = moshi.adapter<Map<String, Any?>>(Map::class.java)
                .nullSafe() as JsonAdapter<Map<String, Any?>>
            val resultMap = jsonAdapter.fromJson(responseString)
            businessCode = (resultMap?.get("code") as? Number)?.toInt()

            // 在这里可以对 responseString 进行统一的业务逻辑处理，
            // 例如：判断token是否过期、统一的错误码处理等。
            // 当前为空，可根据实际需求扩展。
        } catch (e: Exception) {
            // 捕获在处理响应字符串时可能发生的异常。
        }

        // 只有当HTTP状态码为400且能解析出业务码时才修改状态码
        if (response.code == 400 && businessCode != null) {
            // 构建新的响应并返回，避免再次执行网络请求
            val newResponseBody = ResponseBody.create(responseBody?.contentType(), responseString ?: "")
            return response.newBuilder()
                .code(200) // 将400状态码改为200，让OkHttp不抛异常
                .body(newResponseBody).build()
        }

        // 因为原始的 responseBody 流已经被读取消耗掉了，我们必须创建一个新的 ResponseBody，
        // 并将其设置回响应对象中，这样App的其他部分（如ViewModel或Repository）才能正常解析响应数据。
        val newResponseBody = ResponseBody.create(responseBody?.contentType(), responseString ?: "")

        // 使用原始响应的newBuilder()，将新的响应体包装回去，然后构建并返回一个新的响应对象。
        return response.newBuilder().body(newResponseBody).build()
    }
}
